package com.kehutong.common.permission;

import com.kehutong.common.constant.CommonConstant;
import org.coraframework.authz.Subject;
import org.coraframework.authz.SubjectUtil;
import org.coraframework.authz.exception.NotPermissionException;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.orm.jdbc.execute.ICondition;
import org.coraframework.util.Objects;

import java.util.Set;

/**
 * 数据权限
 */
public class DataPermissionQuery {

    private static final String USER_IDENTITY = "DATA_USER_IDENTITY";
    private static final String SUPER_ROLE = "5";

    /**
     * 设置获取用户所有的数据
     *
     * @param condition     条件
     * @param nameDto       权限名字类
     * @param userLoginInfo 传输的用户信息
     */
    public static void setAllDataSql(ICondition condition, PermissionNameDto nameDto, UserLoginInfo userLoginInfo) {
        userLoginInfo = getUserInfo(userLoginInfo);
        if (userLoginInfo == null) {
            return;
        }
        if (isSuper(userLoginInfo)) {
            return;
        }

        if(userLoginInfo.isAllData()){
            return;
        }

        // 设置默认字段
        if (nameDto == null) {
            nameDto = new PermissionNameDto();
        }
        setDefaultName(nameDto);

        // 设置用户信息
        JSONObject jsonObject = new JSONObject();
        setUserInfo(jsonObject, nameDto, userLoginInfo);

        condition.markBegin();
        // 管理数据
        doSetManageSql(condition, jsonObject, nameDto);

        // 下级数据
//        if (jsonObject.getIntValue(USER_IDENTITY) == 1) {
            condition.or();
            doSetChildDepartmentSql(condition, jsonObject, nameDto, true);
//        }

        // 空字段的数据
        condition.or();
        setEmptyDataSql(condition, nameDto);

        condition.markEnd();
    }

    /**
     * 设置获取用户管理的数据
     *
     * @param condition     条件
     * @param nameDto       权限名字类
     * @param userLoginInfo 传输的用户信息
     */
    public static void setManageDataSql(ICondition condition, PermissionNameDto nameDto, UserLoginInfo userLoginInfo) {
        userLoginInfo = getUserInfo(userLoginInfo);
        if (userLoginInfo == null) {
            return;
        }
        if (isSuper(userLoginInfo)) {
            return;
        }

        // 设置默认字段
        if (nameDto == null) {
            nameDto = new PermissionNameDto();
        }
        setDefaultName(nameDto);

        // 管理数据
        JSONObject jsonObject = new JSONObject();
        setUserInfo(jsonObject, nameDto, userLoginInfo);
        doSetManageSql(condition, jsonObject, nameDto);
    }

    public static void setManageDepartmentNoDataSql(ICondition condition, UserLoginInfo userLoginInfo) {
        userLoginInfo = getUserInfo(userLoginInfo);
        if (userLoginInfo == null) {
            return;
        }
        if (isSuper(userLoginInfo)) {
            return;
        }
        if(userLoginInfo.isAllData()){
            return;
        }

        doSetManageDepartmentNoSql(condition, userLoginInfo);
    }

    /**
     * 设置获取下级部门的数据
     *
     * @param condition     条件
     * @param nameDto       权限名字类
     * @param userLoginInfo 传输的用户信息
     */
    public static void setChildDepartmentDataSql(ICondition condition, PermissionNameDto nameDto, UserLoginInfo userLoginInfo) {
        userLoginInfo = getUserInfo(userLoginInfo);
        if (userLoginInfo == null) {
            return;
        }
        if (isSuper(userLoginInfo)) {
            return;
        }

        // 设置默认字段
        if (nameDto == null) {
            nameDto = new PermissionNameDto();
        }
        setDefaultName(nameDto);

        // 下级数据
        JSONObject jsonObject = new JSONObject();
        setUserInfo(jsonObject, nameDto, userLoginInfo);
        if (jsonObject.getIntValue(USER_IDENTITY) == 1) {
            doSetChildDepartmentSql(condition, jsonObject, nameDto, false);
        } else {
            throw new NotPermissionException();
        }
    }

    public static UserLoginInfo getUserInfo(UserLoginInfo userLoginInfo) {
        if (userLoginInfo == null) {
            Subject subject = SubjectUtil.getSubject();
            userLoginInfo = subject.getAttr(CommonConstant.CURRENT_USER_INFO + ":" + subject.getUserId());
        }
        return userLoginInfo;
    }

    private static boolean isSuper(UserLoginInfo userLoginInfo) {
        Set<String> roles = userLoginInfo.getRoles();
        return roles != null && roles.contains(SUPER_ROLE);
    }

    private static void doSetChildDepartmentSql(ICondition condition, JSONObject jsonObject, PermissionNameDto nameDto, boolean isAll) {
        // 下级部门
        JSONArray departmentNos = jsonObject.getJSONArray(nameDto.getDepartmentNos());
        if (Objects.nonEmpty(departmentNos)) {
            condition.markBegin();
            for (int i = 0; i < departmentNos.size(); i++) {
                condition.findInSet(nameDto.getDepartmentNos(), departmentNos.get(i));
                condition.and().notFindInSet(nameDto.getDepartmentNo(), departmentNos.get(i)).or();
            }
            condition.markEnd();
        }
    }

    private static void doSetManageDepartmentNoSql(ICondition condition, UserLoginInfo userLoginInfo) {
        // 指定部门
        Set<String> manageDepartmentNos = userLoginInfo.getManageDepartmentNo();
        if (Objects.nonEmpty(manageDepartmentNos)) {
            condition.and();
            condition.markBegin();
            manageDepartmentNos.forEach(id ->{
                condition.findInSet("parent_ids", id).or();
            });
            condition.markEnd();
            condition.or();
        }

    }

    private static void doSetManageSql(ICondition condition, JSONObject jsonObject, PermissionNameDto nameDto) {
        // 创建人
        condition.markBegin();
        condition.eq(jsonObject, nameDto.getCreateUserId());

        // 指定用户
        condition.or();
        condition.like(jsonObject, nameDto.getManageUserId());

        // 当前部门
        condition.or();
        JSONArray departmentNo = jsonObject.getJSONArray(nameDto.getDepartmentNo());
        if (Objects.nonEmpty(departmentNo)) {
            condition.markBegin();
            for (int i = 0; i < departmentNo.size(); i++) {
                condition.findInSet(nameDto.getDepartmentNo(), departmentNo.get(i)).or();
            }
            condition.markEnd();
        }

        // 指定部门
        JSONArray manageDepartmentNo = jsonObject.getJSONArray(nameDto.getManageDepartmentNo());
        if (Objects.nonEmpty(manageDepartmentNo)) {
            condition.or();
            condition.markBegin();
            for (int i = 0; i < manageDepartmentNo.size(); i++) {
                condition.findInSet(nameDto.getManageDepartmentNo(), manageDepartmentNo.get(i)).or();
            }
            condition.markEnd();
        }
        condition.markEnd();
    }

    private static void setUserInfo(JSONObject jsonObject, PermissionNameDto nameDto, UserLoginInfo userLoginInfo) {
        if (userLoginInfo == null) {
            Subject subject = SubjectUtil.getSubject();
            userLoginInfo = subject.getAttr(CommonConstant.CURRENT_USER_INFO + ":" + subject.getUserId());
        }
        jsonObject.put(nameDto.getCreateUserId(), userLoginInfo.getUserId());
        jsonObject.put(nameDto.getManageUserId(), userLoginInfo.getUserId());
        jsonObject.put(nameDto.getDepartmentNo(), userLoginInfo.getDepartmentNo());
        jsonObject.put(nameDto.getDepartmentNos(), userLoginInfo.getDepartmentNo());
        jsonObject.put(nameDto.getManageDepartmentNo(), userLoginInfo.getManageDepartmentNo());
        jsonObject.put(USER_IDENTITY, userLoginInfo.getIdentity());
    }

    private static void setEmptyDataSql(ICondition condition, PermissionNameDto nameDto) {
        // 创建人为空
        condition.markBegin();
        condition.isNull(nameDto.getCreateUserId());

        // 指定用户为空
        condition.and();
        condition.isNull(nameDto.getManageUserId());

        // 当前部门为空
        condition.and();
        condition.isNull(nameDto.getDepartmentNo());

        // 指定部门为空
        condition.and();
        condition.isNull(nameDto.getManageDepartmentNo());
        condition.markEnd();
    }

    private static void setDefaultName(PermissionNameDto nameDto) {
        if (Objects.isEmpty(nameDto.getCreateUserId())) {
            nameDto.setCreateUserId("createUserId");
        }
        if (Objects.isEmpty(nameDto.getManageUserId())) {
            nameDto.setManageUserId("manageUserId");
        }
        if (Objects.isEmpty(nameDto.getDepartmentNo())) {
            nameDto.setDepartmentNo("departmentNo");
        }
        if (Objects.isEmpty(nameDto.getDepartmentNos())) {
            nameDto.setDepartmentNos("departmentNos");
        }
        if (Objects.isEmpty(nameDto.getManageDepartmentNo())) {
            nameDto.setManageDepartmentNo("manageDepartmentNo");
        }
    }
}
